﻿using System.Collections.Generic;
using Tools.Common.UnitOfWork.Contracts;
using Tools.Domain.Common.Repositories.Contracts;
using Web.App.Infrastructure.ApplicationMessages.Contracts;
using Web.App.Infrastructure.ApplicationMessages.Implementation;
using Web.App.Infrastructure.Context.Contracts;
using Web.App.Infrastructure.CrossCuttingConcerns.Attributes;
using Web.App.Infrastructure.UnitOfWork;
using Webshop20.Application.Operations.Messages;
using Web.App.Infrastructure.Security.Contracts;
using Webshop20.Domain.Catalog.Core;
using Webshop20.Domain.Customers.Core;
using Webshop20.Domain.Security.Authentication.Core;
using Web.App.Infrastructure.ObjectStore.Contracts;
using System;

namespace Webshop20.Application.Operations.Services
{
    public interface ISaveNewRegistrationService : IService
    {
        [Transaction]
        new ISystemMessage Handle(ISystemMessage request);
    }

    public class SaveNewRegistrationService : ServiceBase, ISaveNewRegistrationService
    {
        private IRepository<Account> accountRepository;
        private IRepository<Customer> customerRepository;
        private IRepository<Visitor> visitorRepository;
        private IObjectStoreRepository objectStoreRepository;
        private IEncryptionService encryptionService;

        public SaveNewRegistrationService(IRepository<Account> accountRepository, IObjectStoreRepository objectStoreRepository, IEncryptionService encryptionService, IRepository<Customer> customerRepository, IRepository<Visitor> visitorRepository)
        {
            this.accountRepository = accountRepository;
            this.visitorRepository = visitorRepository;
            this.customerRepository = customerRepository;
            this.encryptionService = encryptionService;
            this.objectStoreRepository = objectStoreRepository;
        }

      
        public new ISystemMessage Handle(ISystemMessage request)
        {
            var saveNewAccountRequest = request as SaveNewRegistrationRequest;

            SaveAccount(saveNewAccountRequest);
            var registrationKey = SaveCustomerAndGetRegistrationKey(saveNewAccountRequest);

            return new SaveNewRegistrationResponse(null, registrationKey);
        }

        //public override ISystemMessage Handle(ISystemMessage request)
        //{
        //    var saveNewAccountRequest = request as SaveNewRegistrationRequest;
        //    IDomainMessage failure = null;
        //    //var transaction = UnitOfWork.Current.BeginTransaction();
        //    var registrationKey = string.Empty;

        //    try
        //    {
        //        SaveAccount(saveNewAccountRequest);
        //        registrationKey = SaveCustomerAndGetRegistrationKey(saveNewAccountRequest);
        //        //transaction.Commit();
        //        UnitOfWork.Current.Flush();

        //    }
        //    catch (Exception)
        //    {
        //        domainMessage = new FailureMessage(
        //            new List<IFailure> { new Failure(null, "PERSISTENCE_FAILED", "", "") }, this.GetType().ToString(),
        //            "Handle", "Neuregistrierung konnte nicht gespeichert werden");
        //        //transaction.Rollback();

        //    }
        //    finally
        //    {
        //        //transaction.Dispose();
        //    }

        //    return new SaveNewRegistrationResponse(failure, registrationKey);


        //}

        private string SaveCustomerAndGetRegistrationKey(SaveNewRegistrationRequest request)
        {
            var customerId = new Guid(request.customerInterimKey);
            var newCustomer = objectStoreRepository.Find(customerId).Data as Customer;
            customerRepository.Save(newCustomer);
            visitorRepository.SaveOrUpdate(new Visitor(new ShoppingCart()){ EMail = newCustomer.EMail, FirstName = newCustomer.FirstName, LastName = newCustomer.LastName, Id = newCustomer.Id});
            objectStoreRepository.Remove(customerId);
            return newCustomer.GenerateRegistrationKey(encryptionService);
        }

        private void SaveAccount(SaveNewRegistrationRequest saveNewAccountRequest)
        {
            var accountId = new Guid(saveNewAccountRequest.AccountInterimKey);
            var newAccount = objectStoreRepository.Find(accountId).Data as Account;
            accountRepository.Save(newAccount);
            objectStoreRepository.Remove(accountId);
        }
    }
}
